<?php
/**
 * Created by PhpStorm.
 * User: yf
 * Date: 2018/5/28
 * Time: 下午6:33
 */

namespace EasySwoole\EasySwoole;

use App\Process\ClearTempCnn;
use App\Process\GroupSysMessage;
use App\Process\OfflineMessage;
use App\WebSocket\WebSocketEvent;
use EasySwoole\Component\TableManager;
use EasySwoole\EasySwoole\Swoole\EventRegister;
use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\Http\Message\Status;
use EasySwoole\Http\Request;
use EasySwoole\Http\Response;
use EasySwoole\ORM\Db\Connection;
use EasySwoole\ORM\DbManager;
use EasySwoole\Socket\Dispatcher;
use App\WebSocket\WebSocketParser;
use EasySwoole\Component\Process\Manager;
use EasySwoole\RedisPool\RedisPool;
use EasySwoole\Redis\Config\RedisConfig;
use EasySwoole\Queue\Driver\Redis;
use EasySwoole\Utility\Time;
use App\Process\Subscribe;
use App\Process\Consumer;
use EasySwoole\Core\Swoole\Process\ProcessManager;
use Swoole\Table;

class EasySwooleEvent implements Event
{

    public static function initialize()
    {
        date_default_timezone_set('Asia/Shanghai');
        //数据库连接池
        $config = new \EasySwoole\ORM\Db\Config(Config::getInstance()->getConf('MYSQL'));
        DbManager::getInstance()->addConnection(new Connection($config));
    }

    public static function mainServerCreate(EventRegister $register)
    {
        $register->add($register::onWorkerStart,function (){
            //数据库链接预热
            DbManager::getInstance()->getConnection()->getClientPool()->keepMin();
        });
        //创建内存表记录在线用户信息
       TableManager::getInstance()->add(
           Config::getInstance()->getConf('CHAT.online_user'),
            [
                'fd'=>['type'=>Table::TYPE_INT,'size'=>20],
                'server'=>['type'=>Table::TYPE_STRING,'size'=>64],#服务器ip
                'nickname'=>['type'=>Table::TYPE_STRING,'size'=>64],#昵称
                'app_user_id'=>['type'=>Table::TYPE_STRING,'size'=>64],#app_user_id
                'head'=>['type'=>Table::TYPE_STRING,'size'=>64],
                'app_id'=>['type'=>Table::TYPE_STRING,'size'=>6],#归属应用
                'type'=>['type'=>Table::TYPE_STRING,'size'=>6],
                'login_time'=>['type'=>Table::TYPE_STRING,'size'=>16],
                'access_key'=>['type'=>Table::TYPE_STRING,'size'=>32],
                'secret_key'=>['type'=>Table::TYPE_STRING,'size'=>32]
            ],
            20240
        );
        //离线消息
        TableManager::getInstance()->add(
            Config::getInstance()->getConf('CHAT.sync_message'),
            [
                'fd'=>['type'=>Table::TYPE_INT,'size'=>20],
                'user_id'=>['type'=>Table::TYPE_STRING,'size'=>24],
            ],
          10240
        );
        //用户归属
        TableManager::getInstance()->add(
            Config::getInstance()->getConf('CHAT.fd_to_app'),
            [
                'access_key'=>['type'=>Table::TYPE_STRING,'size'=>32],
                'secret_key'=>['type'=>Table::TYPE_STRING,'size'=>32],
            ],
            10240
        );
        #用户是否就绪
        TableManager::getInstance()->add(
            Config::getInstance()->getConf('CHAT.user_ready'),
            [
                'user_id'=>['type'=>Table::TYPE_STRING,'size'=>16],
                'status'=>['type'=>Table::TYPE_STRING,'size'=>2],
            ],
            10240
        );
       //redis连接池
       $redisPoolConfig = \EasySwoole\RedisPool\Redis::getInstance()->register('redis',new \EasySwoole\Redis\Config\RedisConfig(Config::getInstance()->getConf('REDIS')));

        //配置连接池连接数
        $redisPoolConfig->setMinObjectNum(10);
        $redisPoolConfig->setMaxObjectNum(50);
        $redisPoolConfig->setAutoPing(10);//设置自动ping的间隔 版本需>=2.1.2，避免连接掉线*/

        //客户端接收群聊订阅
      \EasySwoole\Component\Process\Manager::getInstance()->addProcess(new Subscribe());
        #客户端接收群系统消息订阅
    #    \EasySwoole\Component\Process\Manager::getInstance()->addProcess(new GroupSysMessage());

        //客户端处理私聊队列
       // \EasySwoole\Component\Process\Manager::getInstance()->addProcess(new Consumer());
        #处理刚上线用户的离线消息,关闭离线消息，客户主动拉取
        \EasySwoole\Component\Process\Manager::getInstance()->addProcess(new OfflineMessage());
        #自动清理临时连接
        \EasySwoole\Component\Process\Manager::getInstance()->addProcess(new ClearTempCnn());

        /**
         * **************** websocket控制器 **********************
         */
        // 创建一个 Dispatcher 配置
        $conf = new \EasySwoole\Socket\Config();
        // 设置 Dispatcher 为 WebSocket 模式
        $conf->setType(\EasySwoole\Socket\Config::WEB_SOCKET);

        // 设置解析器对象
        $conf->setParser(new WebSocketParser());
        // 创建 Dispatcher 对象 并注入 config 对象
        $dispatch = new Dispatcher($conf);
        // 给server 注册相关事件 在 WebSocket 模式下  on message 事件必须注册 并且交给 Dispatcher 对象处理
        $register->set(EventRegister::onMessage, function (\swoole_websocket_server $server, \swoole_websocket_frame $frame) use ($dispatch) {
            $dispatch->dispatch($server, $frame->data, $frame);
        });

        //自定义握手事件
        $websocketEvent = new WebSocketEvent();
        $register->set(EventRegister::onHandShake, function (\swoole_http_request $request, \swoole_http_response $response) use ($websocketEvent) {
            $websocketEvent->onHandShake($request, $response);
        });

        //自定义关闭事件
        $register->set(EventRegister::onClose, function (\swoole_server $server, int $fd, int $reactorId) use ($websocketEvent) {
            echo '关闭事件';
            $websocketEvent->onClose($server, $fd, $reactorId);
        });

    }
    /**
     * 数据包 pack处理
     * encode
     * @param $str
     * @return string
     * @author Tioncico
     * Time: 9:50
     */
    public static function encode($str)
    {
        return pack('N', strlen($str)) . $str;
    }

    public static function decode($str)
    {
        $data = substr($str, '4');
        return $data;
    }


/*    public static function onRequest(Request $request, Response $response): bool
    {
        // TODO: Implement onRequest() method.
        return true;
    }*/
    public static function onRequest(Request $request, Response $response): bool
    {
        // TODO: Implement onRequest() method.
        $response->withHeader('Access-Control-Allow-Origin', '*');
        $response->withHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
        $response->withHeader('Access-Control-Allow-Credentials', 'true');
        $response->withHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
        if ($request->getMethod() === 'OPTIONS') {
            $response->withStatus(Status::CODE_OK);

            return false;
        }
        return true;
    }

    public static function afterRequest(Request $request, Response $response): void
    {
        // TODO: Implement afterAction() method.
    }
}